#include "stdafx.h"
#include "SocketOptionFactory.h"

using namespace Adaptive::Network::Sockets;

SocketOptionFactory::SocketOptionFactory()
{
}

SocketOptionCollection^ SocketOptionFactory::GetSocketOptions()
{
	SocketOptionCollection^ returnValue = nullptr;

	returnValue = gcnew SocketOptionCollection();
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::AcceptConnection) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::Broadcast) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::Debug) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::DontLinger) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::DontRoute) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::Socket, SocketOptionName::Error) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::KeepAlive) );
	returnValue->Add( gcnew LingerSocketOption(SocketOptionLevel::Socket, SocketOptionName::Linger) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::Socket, SocketOptionName::ReceiveBuffer) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::Socket, SocketOptionName::SendBuffer) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::ReuseAddress ) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::Socket, SocketOptionName::Type ) );

	return returnValue;
}
SocketOptionCollection^ SocketOptionFactory::GetIpOptions()
{
	SocketOptionCollection^ returnValue = nullptr;

	returnValue = gcnew SocketOptionCollection();
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::IP, SocketOptionName::HeaderIncluded) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::IP, SocketOptionName::MulticastLoopback) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::IP, SocketOptionName::UseLoopback) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::IP, SocketOptionName::IPOptions) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::IP, SocketOptionName::IpTimeToLive) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::IP, SocketOptionName::MulticastTimeToLive) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::IP, SocketOptionName::TypeOfService) );

	return returnValue;
}
SocketOptionCollection^ SocketOptionFactory::GetTcpOptions()
{
	SocketOptionCollection^ returnValue = nullptr;

	returnValue = gcnew SocketOptionCollection();
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Tcp, SocketOptionName::BsdUrgent) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Tcp, SocketOptionName::Expedited) );
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Tcp, SocketOptionName::NoDelay) );

	return returnValue;
}
SocketOptionCollection^ SocketOptionFactory::GetUdpOptions()
{
	SocketOptionCollection^ returnValue = nullptr;

	returnValue = gcnew SocketOptionCollection();
	returnValue->Add( gcnew BooleanSocketOption(SocketOptionLevel::Udp, SocketOptionName::NoChecksum) );
	returnValue->Add( gcnew DwordSocketOption(SocketOptionLevel::Udp, SocketOptionName::ChecksumCoverage) );

	return returnValue;
}
ISocketOption^ SocketOptionFactory::CreateOptionByName(SocketOptionName name)
{
	ISocketOption^ returnValue = nullptr;

	switch(name)
	{
	case 2:
		if (name.ToString() == "AcceptConnection")
			returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::AcceptConnection);
		else if (name.ToString() == "HeaderIncluded")
			returnValue = gcnew BooleanSocketOption(SocketOptionLevel::IP, SocketOptionName::HeaderIncluded);
		else if (name.ToString() == "BsdUrgent")
			returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Tcp, SocketOptionName::BsdUrgent);
		else if (name.ToString() == "Expedited")
			returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Tcp, SocketOptionName::Expedited);
		break;

	case SocketOptionName::Broadcast:
		returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::Broadcast);
		break;

	case 1:

		if (name.ToString() == "Debug")
			returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::Debug);
		else if (name.ToString() == "NoDelay")
			returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Tcp, SocketOptionName::NoDelay);
		else if (name.ToString() == "NoChecksum")
			returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Udp, SocketOptionName::NoChecksum);
		else if (name.ToString() == "IPOptions")
			returnValue = gcnew DwordSocketOption(SocketOptionLevel::IP, SocketOptionName::IPOptions);
	
		break;

	case SocketOptionName::DontLinger:
		returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::DontLinger);
		break;

	case SocketOptionName::DontRoute:
		returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::DontRoute);
		break;

	case SocketOptionName::Error:
		returnValue = gcnew DwordSocketOption(SocketOptionLevel::Socket, SocketOptionName::Error);
		break;

	case SocketOptionName::KeepAlive:
		returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::KeepAlive);
		break;

	case SocketOptionName::Linger:
		returnValue = gcnew LingerSocketOption(SocketOptionLevel::Socket, SocketOptionName::Linger);
		break;

	case SocketOptionName::ReceiveBuffer:
		returnValue = gcnew DwordSocketOption(SocketOptionLevel::Socket, SocketOptionName::ReceiveBuffer);
		break;

	case SocketOptionName::SendBuffer:
		returnValue = gcnew DwordSocketOption(SocketOptionLevel::Socket, SocketOptionName::SendBuffer);
		break;

	case 4:

		if (name.ToString() == "ReuseAddress")
			returnValue = gcnew BooleanSocketOption(SocketOptionLevel::Socket, SocketOptionName::ReuseAddress);
		else if (name.ToString() == "IpTimeToLive")
			returnValue = gcnew DwordSocketOption(SocketOptionLevel::IP, SocketOptionName::IpTimeToLive);
		break;

	case SocketOptionName::Type:
		returnValue = gcnew DwordSocketOption(SocketOptionLevel::Socket, SocketOptionName::Type);
		break;

	case SocketOptionName::MulticastLoopback:
		returnValue = gcnew BooleanSocketOption(SocketOptionLevel::IP, SocketOptionName::MulticastLoopback);
		break;

	case SocketOptionName::UseLoopback:
		returnValue = gcnew BooleanSocketOption(SocketOptionLevel::IP, SocketOptionName::UseLoopback);
		break;

	case SocketOptionName::MulticastTimeToLive:
		returnValue = gcnew DwordSocketOption(SocketOptionLevel::IP, SocketOptionName::MulticastTimeToLive);
		break;

	case SocketOptionName::TypeOfService:
		returnValue = gcnew DwordSocketOption(SocketOptionLevel::IP, SocketOptionName::TypeOfService);
		break;

	case SocketOptionName::ChecksumCoverage:
		returnValue = gcnew DwordSocketOption(SocketOptionLevel::Udp, SocketOptionName::ChecksumCoverage);
		break;

	default:
		returnValue = nullptr;
		break;
	}
	return returnValue;
}